﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Identity;
using Eqwww.Domain.Models.SystemManage;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
using Eqwww.Data;
using System.Linq;
using Eqwww.Code;
using Eqwww.Domain;
using Microsoft.EntityFrameworkCore;

namespace Eqwww.App.SystemManage
{
    public class ModuleApp
    {
        private ApplicationDbContext _context;
        private IModelHandler _modelHandler;
        private DatabaseLogApp _dbLogApp;
        public ModuleApp(ApplicationDbContext context, IModelHandler modelHandler, DatabaseLogApp databaseLogApp)
        {
            _context = context;
            _modelHandler = modelHandler;
            _dbLogApp = databaseLogApp;
        }

        public ModelResult Create(ModuleModel model)
        {
            if (_context.Sys_Modules.Any(x => x.Code.ToUpper() == model.Code.ToUpper()))
            {
                return Common.ErrorResult("编码不能重复！");
            }
            if (string.IsNullOrEmpty(model.ParentId))
            {
                model.Layer = 0;
            }
            else
            {
                var parent = _context.Sys_Modules.FirstOrDefault(x => x.Id == model.ParentId);
                if (parent == null)
                    return Common.ErrorResult("未找到指定的上级模块！");
                model.Layer = parent.Layer + 1;
            }
            _modelHandler.Create(model);
            _context.Sys_Modules.Add(model);
            _dbLogApp.LogCreateInformation(model.Id, model, "创建模块");
            _context.SaveChanges();
            return Common.SuccessResult();

        }

        public ModuleModel Get(string id)
        {
            return _context.Sys_Modules.AsNoTracking().FirstOrDefault(x => x.Id == id);
        }

        public ModuleModel GetInclude(string id)
        {
            return _context.Sys_Modules.Include(x=>x.CreateUser).Include(x=>x.LastUpdateUser).Include(x=>x.DeleteUser).Include(x=>x.Parent).FirstOrDefault(x => x.Id == id);
        }

        public ModelResult Update(ModuleModel model)
        {
            if (_context.Sys_Modules.Any(x => x.Code.ToUpper() == model.Code.ToUpper() && x.Id != model.Id))
            {
                return Common.ErrorResult("编码不能重复！");
            }
            var oldModel = _context.Sys_Modules.AsNoTracking().FirstOrDefault(x => x.Id == model.Id);
            if (oldModel == null)
            {
                return Common.ErrorResult("实体不存在");
            }
            if (oldModel.IsSystem == true)
            {
                return Common.ErrorResult("系统模块不允许修改");
            }
            if (GetDescendantIdsWithSelf(model.Id).Contains(model.ParentId))
            {
                return Common.ErrorResult("不能将当前模块移动到自身及子孙模块下");
            }
            if (oldModel.ParentId != model.ParentId)
            {
                if (string.IsNullOrEmpty(model.ParentId))
                {
                    model.Layer = 0;
                }
                else
                {
                    var parent = _context.Sys_Modules.AsNoTracking().FirstOrDefault(x => x.Id == model.ParentId);
                    if (parent == null)
                        return Common.ErrorResult("未找到指定的上级模块！");
                    model.Layer = parent.Layer + 1;
                }
            }

            _modelHandler.Update(model);
            _context.Update(model);

            _dbLogApp.LogUpdateInformation(model.Id, model, "更新模块");
            _context.SaveChanges();
            return Common.SuccessResult();
        }

        public ModelResult Remove(string id)
        {
            var model = _context.Sys_Modules.FirstOrDefault(x => x.Id == id);
            if (model != null)
            {
                _modelHandler.Delete(model);
                _context.UpdateModel(model);
                _dbLogApp.LogRemoveInformation(model.Id,model, "逻辑删除模块");
                _context.SaveChanges();
            }
            return Common.SuccessResult();
        }

        public ModelResult UpdateIsSystem(string id, bool issystem)
        {
            var model = _context.Sys_Modules.FirstOrDefault(x => x.Id == id);
            if (model == null)
                return Common.ErrorResult("未找到指定id的实体");

            model.IsSystem = issystem;
            _context.Update(model);
            _dbLogApp.LogUpdateInformation(id, model, "更新模块【系统】标识【" + issystem.ToString() + "】");
            _context.SaveChanges();
            return Common.SuccessResult();
        }

        public IEnumerable<string> GetDescendantIdsWithSelf(string id)
        {
            var list = new List<string>();
            if (string.IsNullOrEmpty(id))
                return list;
            list.Add(id);
            var childrenIds = (from p in _context.Sys_Modules.AsNoTracking().Where(x => x.ParentId == id) select p.Id).ToList();
            if (childrenIds.Count() <= 0)
                return list;
            else
            {
                foreach(var item in childrenIds)
                {
                    list.AddRange(GetDescendantIdsWithSelf(item));
                }
            }
            return list;
        }

        public IQueryable<ModuleModel> IQueryable(bool containDeleted=false)
        {
            var expression = ExtLinq.True<ModuleModel>();
            if (!containDeleted)
                expression = expression.And(x => x.DeleteMark != true);
            return _context.IQueryable(expression);
        } 

        public IEnumerable<TreeCollapseModel> GetTreeCollapseItems()
        {
            var data = _context.IQueryable<ModuleModel>().Where(x => x.DeleteMark != true);
            var result = from module in data
                         select new TreeCollapseModel
                         {
                             Id = module.Id,
                             Text = module.Name,
                             ParentId = module.ParentId,
                             SortCode = module.SortCode,
                             Url = module.Url
                         };
            return result;
            
        }

        public IList<ModuleModel> GetList()
        {
            var exp = ExtLinq.True<ModuleModel>();
            exp = exp.And(x => x.DeleteMark != true);
            var data = _context.Set<ModuleModel>().Where(exp).OrderBy(x => x.SortCode).ToList();
            return data;
        }
    }
}
